package org.ant.properties;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class PropertyManager {

	private static PropertyManager pm;
	private static final String PATH = "properties/properties.xml";
	private static final String DEFAULT_PATH = "properties/default_properties.xml";
	public static final String ROOT = "root";
	public static final String PROPERTIES = "properties";
	public static final String KEY = "key";
	public static final String CLASS = "class";
	public static final String PROPERTY = "property";

	public static PropertyManager getInstance() {
		if (pm == null) {
			pm = new PropertyManager();
		}
		return pm;
	}

	private Hashtable<String, Property> properties;
	private Hashtable<String, Property> defaultProperties;

	private PropertyManager() {
		init();
		load(PATH);
	}

	protected void init() {
		properties = new Hashtable<String, Property>();
	}

	public boolean load(String path) {
		SAXReader reader = new SAXReader();
		Document doc = null;
		try {
			doc = reader.read(new File(path));
		} catch (DocumentException e) {
			e.printStackTrace();
			return false;
		}

		Element root = doc.getRootElement();
		Element props = root.element(PROPERTIES);
		
		List<Element> propList = props.elements(PROPERTY);
		for (Element element : propList) {
			if (element.getName().equals(PROPERTY)) {
				String key = element.element(KEY).getText();
				String className = element.element(CLASS).getText();
				Property p = null;
				try {
					 p = (Property) Class.forName(className).newInstance();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
				p.init(element);
				
				if(path.equals(DEFAULT_PATH)){
					defaultProperties.put(key, p);
				}
				else{
					properties.put(key, p);
				}
			}
		}
		return true;
	}

	public void save() {
		Document doc = DocumentHelper.createDocument();
		Element root = doc.addElement(ROOT);
		Element propList = root.addElement(PROPERTIES);

		Enumeration<String> en = properties.keys();
		while (en.hasMoreElements()) {
			String key = en.nextElement();
			Property property = properties.get(key);
			Element child = propList.addElement(PROPERTY);
			child.addElement(KEY).addText(key);
			child.addElement(CLASS).addText(property.getClass().getName());
			child.add(property.getElement());
		}

		try {
			File file = new File(PATH);
			FileOutputStream fs = new FileOutputStream(file);
			fs.write(doc.asXML().getBytes());
			fs.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public Property getProperty(String key) {
		return properties.get(key);
	}
	
	public Property getDefault(String key) {
		if (defaultProperties == null) {
			defaultProperties = new Hashtable<String,Property>();
			load(DEFAULT_PATH);
		}
		return defaultProperties.get(key);
	}
	
	public static void main(String args[]) {
		PropertyManager pm = PropertyManager.getInstance();
		Property p = pm.getProperty("hello");
		if(p instanceof DefaultProperty){
			DefaultProperty dp = (DefaultProperty)p;
			System.out.println(dp.getValue());
		}
		pm.save();
	}
}
